﻿using ILRuntime.CLR.Method;
using ILRuntime.CLR.TypeSystem;
using ILRuntime.Runtime.Enviorment;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Invocation : MonoBehaviour
{
    AppDomain appdomain;
    // Use this for initialization
    void Start()
    {
        StartCoroutine(LoadHotFixAssembly());
    }

    IEnumerator LoadHotFixAssembly()
    {
        appdomain = new ILRuntime.Runtime.Enviorment.AppDomain();
#if UNITY_ANDROID
        WWW www = new WWW(Application.streamAssetsPath + "/HotFix_Project.dll");
#else
        WWW www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.dll");
#endif
        while (!www.isDone)
            yield return null;
        if (!string.IsNullOrEmpty(www.error))
            UnityEngine.Debug.LogError(www.error);
        byte[] dll = www.bytes;
        www.Dispose();

#if UNITY_ANDROID
                www = new WWW(Application.streamingAssetsPath + "/HotFix_Project.pdb");
#else
        www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.pdb");
#endif
        while (!www.isDone)
            yield return null;
        if (!string.IsNullOrEmpty(www.error))
            UnityEngine.Debug.LogError(www.error);
        byte[] pdb = www.bytes;
        using (System.IO.MemoryStream fs = new System.IO.MemoryStream(dll))
        {
            using (System.IO.MemoryStream p = new System.IO.MemoryStream(pdb))
            {
                appdomain.LoadAssembly(fs, p, new Mono.Cecil.Pdb.PdbReaderProvider());
            }
        }
        InitializeILRuntime();
        OnHotFixLoaded();

        yield return null;
    }

    void InitializeILRuntime()
    {
    }

    void OnHotFixLoaded()
    {
        appdomain.Invoke("HotFix_Project.InstanceClass", "StaticFuncTest", null, null);
        appdomain.Invoke("HotFix_Project.InstanceClass", "StaticFunTest2", null, 123);

        //预先获得IMethod，降低每次调用查找方法消耗的时间
        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        //根据方法名称和参数个数获取方法
        IMethod method = type.GetMethod("StaticFunTest", 0);

        appdomain.Invoke(method, null, null);

        IType intType = appdomain.GetType(typeof(int));
        List<IType> paramList = new List<ILRuntime.CLR.TypeSystem.IType>();
        paramList.Add(intType);
        method = type.GetMethod("StaticFunTest2", paramList, null);
        appdomain.Invoke(method, null, 456);

        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass", new object[] { 233 });
        object obj2 = ((ILType)type).Instantiate();

        Debug.Log("调用成员方法");
        int id = (int)appdomain.Invoke("HotFix_Project.InstanceClass", "get_ID", obj, null);
        Debug.Log("!!HotFix_Project.InstancClass.ID = " + id);
        id = (int)appdomain.Invoke("HotFix_Project.InstanceClass", "get_ID", obj2, null);
        Debug.Log("!!HotFix_Project.InstancClass.ID = " + id);

        Debug.Log("调用泛型方法");
        IType stringType = appdomain.GetType(typeof(string));
        IType[] genericArguments = new IType[] { stringType };
        appdomain.InvokeGenericMethod("HotFix_Project.InstanceClass", "GenericMethod", genericArguments, null, "TestString");

        Debug.Log("获取泛型方法的IMethod");
        paramList.Clear();
        paramList.Add(intType);
        genericArguments = new IType[] { intType };
        method = type.GetMethod("GenericMethod", paramList, genericArguments);
        appdomain.Invoke(method, null, 33333);
    }

    // Update is called once per frame
    void Update()
    {

    }
}
